package com.runa.protocol.dto;

import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.enums.ModbusDataType;
import com.runa.protocol.enums.ModbusFunctionCode;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.DigitalUtil;

import java.math.BigDecimal;

import static com.runa.protocol.enums.ModbusFunctionCode.*;

public class ModbusPoint extends PlcPoint implements IPoint {

    private Integer modbusAddress;

    private Integer deviation;

    private Object value;

    public ModbusPoint(){}

    public ModbusPoint(Integer id,
               String code, ModbusDataType dataType,
               Integer modbusAddress, ByteOrder byteOrder, Integer deviation) {
        this.id = id;
        this.code = code;
        this.dataType = dataType;
        this.modbusAddress = modbusAddress;
        this.byteOrder = byteOrder;
        this.deviation = deviation;
    }

    @Override
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public ModbusDataType getDataType() {
        return dataType;
    }

    public void setDataType(ModbusDataType dataType) {
        this.dataType = dataType;
    }

    @Override
    public Integer getAddress() {
        return modbusAddress;
    }

    public Integer getRegisterAddress() {
        return modbusAddress < 100000 ? modbusAddress - (modbusAddress / 10000 * 10000) : modbusAddress - (modbusAddress / 100000 * 100000);
    }

    public void setModbusAddress(int modbusAddress) {
        this.modbusAddress = modbusAddress;
    }

    @Override
    public ByteOrder getByteOrder() {
        return byteOrder;
    }

    public void setByteOrder(ByteOrder byteOrder) {
        this.byteOrder = byteOrder;
    }

    @Override
    public Integer getDeviation() {
        return deviation;
    }

    @Override
    public Object getValue() {
        return value;
    }

    public byte[] getByteValues() {
        switch (dataType) {
            case Modbus_Int16:
            case Modbus_UInt16:
                return ByteUtil.shortToByte((short)value, byteOrder);
            case Modbus_Int32:
            case Modbus_UInt32:
                return ByteUtil.intToByte((int)value, byteOrder);
            case Modbus_Float:
                return ByteUtil.floatToByte((float)value, byteOrder);
        }
        return null;
    }

    public ModbusFunctionCode readCode() throws Exception {
        int type = modbusAddress > 10000 ? DigitalUtil.highest(modbusAddress) : 0;
        switch (type) {
            case 0:
                return READ_COILS;
            case 1:
                return READ_INPUTS;
            case 3:
                return READ_INPUT_REGISTERS;
            case 4:
                return READ_HOLDING_REGISTERS;
            default:
                throw new Exception("非法点位地址");
        }
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public void constructValue(Object value) {
        if(value == null) {
            return;
        }
        Class<?> valueClass = value.getClass();
        if(valueClass == Boolean.class) {
            this.value = value;
        } else if(valueClass == BigDecimal.class){
            BigDecimal decimal = (BigDecimal) value;
            switch (dataType) {
                case Modbus_Int16:
                case Modbus_UInt16:
                    this.value = decimal.shortValue();
                    break;
                case Modbus_Int32:
                case Modbus_UInt32:
                    this.value = decimal.intValue();
                    break;
                case Modbus_Float:
                    this.value = decimal.floatValue();
                    break;
                case Modbus_Double:
                    this.value = decimal.doubleValue();
                    break;
                default:
            }
        }
    }







}
